Skip to content

S01-14 JavaSE-异常处理

[TOC]

问题引入

java
public class Exception01 {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        int res = num1 / num2; // 运行时抛出ArithmeticException
        System.out.println("程序继续运行...."); // 不会执行
    }
}

解决方案-try-catch

java
package com.hspedu.exception_;

public class Exception01 {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;

        try {
            int res = num1 / num2; // 可能抛出异常的代码
        } catch (Exception e) {
            // 异常处理逻辑
            System.out.println("出现异常的原因=" + e.getMessage());
        }

        System.out.println("程序继续运行...."); // 会执行
    }
}

异常介绍

基本概念

Java中,程序执行中的不正常情况称为异常(语法错误和逻辑错误不是异常)。

异常分类

  1. Error(错误):JVM无法解决的严重问题(如StackOverflowError、OOM),程序崩溃。
  2. Exception(异常):一般性问题,可通过代码处理,分为:
    • 运行时异常(RuntimeException及其子类):编程逻辑错误,编译器不检查
    • 编译时异常:编译器要求必须处理的异常

异常体系图

Serializable <- Object <- Throwable
                          /      \
                         /        \
                      Error    Exception
                      /          /      \
                     /          /        \
           StackOverflowError  RuntimeException  编译时异常
                                  /
                                 /
                   NullPointerException、ArithmeticException、
                   ArrayIndexOutOfBoundsException、ClassCastException、
                   NumberFormatException

常见的运行时异常

1) NullPointerException(空指针异常)

java
package com.hspedu.exception_;

public class NullPointerException_ {
    public static void main(String[] args) {
        String name = null;
        System.out.println(name.length()); // 抛出空指针异常
    }
}

2) ArithmeticException(数学运算异常)

java
package com.hspedu.exception_;

public class ArithmeticException_ {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        System.out.println(num1 / num2); // 抛出算术异常
    }
}

3) ArrayIndexOutOfBoundsException(数组下标越界异常)

java
package com.hspedu.exception_;

public class ArrayIndexOutOfBoundsException_ {
    public static void main(String[] args) {
        int[] arr = {1,2,4};
        for (int i = 0; i <= arr.length; i++) {
            System.out.println(arr[i]); // i=3时抛出异常
        }
    }
}

4) ClassCastException(类型转换异常)

java
package com.hspedu.exception_;

public class ClassCastException_ {
    public static void main(String[] args) {
        A b = new B(); // 向上转型
        C c2 = (C)b; // 向下转型失败,抛出类型转换异常
    }
}

class A {}
class B extends A {}
class C extends A {}

5) NumberFormatException(数字格式不正确异常)

java
package com.hspedu.exception_;

public class NumberFormatException_ {
    public static void main(String[] args) {
        String name = "韩顺平教育";
        int num = Integer.parseInt(name); // 抛出数字格式异常
    }
}

编译异常

常见编译异常

  • SQLException:数据库操作异常
  • IOException:文件操作异常
  • FileNotFoundException:文件未找到异常
  • ClassNotFoundException:类未找到异常
  • EOFException:文件末尾异常
  • IllegalArgumentException:参数异常

案例演示

java
package com.hspedu.exception_;

import java.io.FileInputStream;
import java.io.IOException;

public class Exception02 {
    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("d:\\aa.jpg");
            int len;
            while ((len = fis.read()) != -1) {
                System.out.println(len);
            }
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

异常处理方式

  1. try-catch-finally:捕获异常,自行处理
  2. throws:抛出异常,由调用者处理

try-catch-finally 执行流程

java
try {
    // 可能抛出异常的代码
} catch (异常类型 e) {
    // 异常处理逻辑
} finally {
    // 无论是否异常,都执行(释放资源)
}

throws 处理流程

java
public static void 方法名() throws 异常类型 {
    // 可能抛出异常的代码
}

try-catch 异常处理

基本语法

java
try {
    // 可疑代码
} catch (异常类型1 e) {
    // 处理异常1
} catch (异常类型2 e) {
    // 处理异常2
} finally {
    // 释放资源
}

注意事项

  1. 异常发生后,try块后续代码不执行,直接进入catch块
  2. 无异常时,不执行catch块
  3. 多个catch块时,子类异常在前,父类异常在后
  4. try-finally配合使用:不捕获异常,程序崩溃但finally仍执行

案例演示(TryCatchDetail.java)

java
package com.hspedu.try_;

public class TryCatchDetail {
    public static void main(String[] args) {
        try {
            String str = "韩顺平";
            int a = Integer.parseInt(str);
            System.out.println("数字:" + a);
        } catch (NumberFormatException e) {
            System.out.println("异常信息=" + e.getMessage());
        } finally {
            System.out.println("finally 代码块被执行...");
        }
        System.out.println("程序继续...");
    }
}

多catch案例(TryCatchDetail02.java)

java
package com.hspedu.try_;

public class TryCatchDetail02 {
    public static void main(String[] args) {
        try {
            Person person = new Person();
            person = null;
            System.out.println(person.getName()); // NullPointerException
            int n1 = 10;
            int n2 = 0;
            int res = n1 / n2; // ArithmeticException
        } catch (NullPointerException e) {
            System.out.println("空指针异常=" + e.getMessage());
        } catch (ArithmeticException e) {
            System.out.println("算术异常=" + e.getMessage());
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

class Person {
    private String name = "jack";
    public String getName() {
        return name;
    }
}

throws 异常处理

基本语法

java
public static void readFile(String file) throws FileNotFoundException {
    FileInputStream fis = new FileInputStream("d://aa.txt");
}

注意事项

  1. 编译异常必须处理(try-catch或throws)
  2. 运行时异常默认采用throws处理
  3. 子类重写父类方法时,抛出异常类型需与父类一致或为其子类
  4. 若方法内已try-catch处理异常,则无需throws

案例演示(ThrowsDetail.java)

java
package com.hspedu.throws_;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class ThrowsDetail {
    public static void main(String[] args) {
        f2();
    }

    public static void f2() {
        // 运行时异常,默认throws处理
        int n1 = 10;
        int n2 = 0;
        double res = n1 / n2;
    }

    public static void f1() throws FileNotFoundException {
        // 编译异常,需throws或try-catch
        f3();
    }

    public static void f3() throws FileNotFoundException {
        FileInputStream fis = new FileInputStream("d://aa.txt");
    }
}

class Father {
    public void method() throws RuntimeException {
    }
}

class Son extends Father {
    // 子类重写方法,抛出异常为父类异常的子类
    @Override
    public void method() throws ArithmeticException {
    }
}

自定义异常

步骤

  1. 定义类,继承Exception或RuntimeException
  2. 继承Exception:编译异常
  3. 继承RuntimeException:运行异常(推荐)

案例演示(CustomException.java)

java
package com.hspedu.customexception_;

public class CustomException {
    public static void main(String[] args) {
        int age = 180;
        // 年龄不在18-120之间,抛出自定义异常
        if (!(age >= 18 && age <= 120)) {
            throw new AgeException("年龄需要在18~120 之间");
        }
        System.out.println("你的年龄范围正确.");
    }
}

// 自定义运行时异常
class AgeException extends RuntimeException {
    public AgeException(String message) {
        super(message);
    }
}

throw 和 throws 的区别

特性throwthrows
意义手动生成异常对象异常处理的一种方式
位置方法体中方法声明处
后面跟的内容异常对象异常类型